/*Author:S.Genikhov
Creatin Date:
Last modified:11/Sept/2010
Reviewed by :

Version 3 with possiblitiest to : Login,get,Bye and simple Security check.
Support only TCP connection.

Short project description:
Bases reallisation of FTP server command like : cd ,send recieve file and commands,
by using of state machine*/

#ifndef __INTERNALFTPSERVER__
#define __INTERNALFTPSERVER__

#include "genserver.h"
#include "iterbintreeKM.h"
#include "ftpserver.h"
#include "genserver.h"

#include "ftpprotocol.h"


#ifdef _unitest_ftp_server_ /*I need for white box testing static functions*/
#define static
#endif


#define     EXPTMESSIZE                 (10)
#define     FTP_NUM_OF_WRONG_PASSW      (3) /*NUMBER OF TIMES TO INPUT THE ILLIGAL PASSWORD*/

#define     PWDSIZE                     (100)
#define     MAXIMALPATH                 (10000)
#define     OUT
#define     IN
#define     INOUT

typedef int  key;
typedef enum state       { ERR_S ,USER_S,PASS_S,WAIT_S,NUMSTATE_S} state_e;

typedef enum modes            { COMND_M, FILE_M,NUMOFMODES_M} mode_e;
typedef enum    isDropMes_t   {NOTDROP_MES,DROP_MES} FTPisDropMess ;


struct userlogin
{
    char    m_username[USERNAMESIZE];
    char    m_userpass[USERNAMESIZE];
    int     m_logcount;
};

typedef struct FTPclient_t
{
    key                 m_key;
    struct userlogin*   m_login;
    char*               m_pwdirect;
    state_e             m_state;/*From Transaction Table*/
    mode_e              m_modes;/*COMMAND or FILE*/
    FTPisDropMess       m_isDropMessage;/*Flag to drop or not drop messages from this client*/
}
FTPcln;

typedef struct FTPattr_t
{
    GenSv*      m_sv;
    FTPServ*    m_ft;
    void*       m_param;
    FTPcln*     m_cl;
}FTPattr;

typedef int (*FTPfunc)(FTPattr*);
typedef struct FTPcell_t
{
    FTPfunc    m_func;
    state_e    m_nextstate;
    state_e    m_nextfailstate;
}
 FTPcell;


typedef void (*ModeFunc) (FTPattr* _attr,void* _buf,size_t _bufsize);
struct FTPserver_t
{
     BinTree*           m_userlogin;
     BinTree*           m_Clients;/*Tree of clients structs*/
     FTPcell            m_transTable[FTP_NUMEVENT_E][NUMSTATE_S];/*state mashien*/
     char               m_rootdirectory[MAXIMALPATH];
     ModeFunc           m_ModeFunc[NUMOFMODES_M];/* 2 functions: one of User send command, 2 client sedn or recieve File*/
     GenSv*             m_gs;
     char               m_events[FTP_NUMEVENT_E][COMMANDLENGTH];
     FTPfunc            m_func[FTP_NUMEVENT_E];
};




/*********InnternalFuncions******************************************************************/
/*Initiallizing of Generic server*/
GenSv* FTPInitOfGenserv(FTPServ* _ft,int _port);

/*Insert the  couples of existed : username + password  from supplyed file to login Tree*,
If fails returns 1 and write error description into stderr, if success returns 0*/
int FTPLoadUsersFromFile(BinTree* _userlogin,char* _filename);

/*Gets the tree and free all data in it.
Not DELETE the Tree
If stored data is structure contains dinamically allocated memory DON'T free these memory areas, don'e use this function*/
void FTPDeleteAllDataInTree(BinTree* _userlogin);

/*returns 1 if buffer size oversize the MAXCOMMANDSIZEj*/
int FTPsecuritycheck(char* _beffer);

/*Simple devide command promt in two parts devided by " "(space).It suppose that 1st string
is event and second is param.
Checks the input lenght by using the FTPsecuritycheck.
Returns 0 if o.k and 1 if fails*/
int FTPparser(void* _buffer,OUT char* _command,OUT char* _param);

/*Gets  line and devide it into tokes _user and _password , tockens can be separated by " ",\t,\n,\r*/
int FTPLogFileParsing(char* _line,OUT char* _user,OUT char* _password);

/*Gets headbufWithData - data package wich starts at position  headbufWithData+sizeof(Header Size),
 Funciton fills header returns size of data + Header Size. _error num has to be filled according to FTPresponds*/
size_t FTPFillHeadr(INOUT void* _headbufWithData,
                        size_t _positon, uint _islast, uint _error,
                        uint _datasize,uint _iscommand);

/*Reads data from _packet and fill _header*/
void FTPReadHeadr(void* _packet,OUT FTPHead* _header);

/*Get the client strcrut from tree,  if client not found returns 0*/
FTPcln* FTPGetClientStruct(int  _idclient,FTPattr* _attr);
/*Returns index of found species in a list of string,
if object not found returns -1*/
int FTPFinedInListOfStr(char* _str, char* _liststr,int _sizeoflist, int _lenghtstr);

/*Function send or Server responds placed in protocol or rNum -  is appropriative index of "respond" from ftpprotocol
Strings with maximal total lenthg up to 1500 bytes includes FTPHeader,
If resposnd is sendted the _str value has to be 0*,
void FTPServerRespond(FTPattr* _atr,size_t rNum,char* 0) in this case respond with rNum will be send*/
void FTPServerRespond(FTPattr* _atr,size_t rNum,char* _str );

/*The help function to FTPUserCd.It accept in _atr->m_param the new path. Makes inside the buffer allocation
 with size enoght to contain the full newpath. If somthing wrong happens, sent respond
to client and free allocated memory. In fails case returns 0. If success returns pointer to allocated buffer
and put in OUT parameter Lengpath is the lenght of string INCLUDES  '\0'*/
char* FTPMPrepareNewClientPwd(FTPattr* _atr,OUT size_t* _lengpath);
/******************Transaction Table***************************************************/
/*All functions returns -1 as error and other value if o.k*/
int FTPErr(FTPattr* _param);
int FTPUserErr(FTPattr* _param);
int FTPPassErr(FTPattr* _param);
int FTPCommErr(FTPattr* _atr);

/*If user find returns it index in list , if not returns -1*/
int FTPUser(FTPattr* _atr);

/*If user find returns it index in list , if not returns -1*/
int FTPPass(FTPattr* _atr);

/*Disconnect client, by actiovation of Callback "ClientDiscn"*/
int FTPUserDisc(FTPattr* _atr);

/*Open file supplyed by argument , and transfer data to client*/
int FTPUserGet(FTPattr* _atr);

/*Chages the pwd of client. Accepted as relative path wich has to stars from "." or ".." as
complete path wich has to start from /. If correct path was provided sent to client the completely new path
cd . - like pwd in linux*/
int FTPUserCd(FTPattr* _atr);

/*Shows the content of current client directory*/
int FTPls(FTPattr* _atr);

int FTPComm(FTPattr* _param);

/********************Client Mode function***************************************************************8*/
void FTPComMode(FTPattr* _attr,void* _buf,size_t _bufsize);
void FTPFileMode(FTPattr* _attr,void* _buf,size_t _bufsize);




/*************CallBack Declaration *********************************************************************/
/*Returns size of Package without header.
If header iscommand == Command , so the max messag size has to be less than MAXCOMMANDSIZE*
If pack size is oversize the returns  0*/
size_t Headrfunc(void* _buf,int _idclient,void* _attribut);
void NewClient(int _idclient,void* _attribut);
void NewMessage(int _IDclient,void* _app, void*  _buf,size_t _mesSize);
void NewExeption(int _IDclient,void* _app, void*  _buf,size_t _mesSize);
void ClientDiscn(int _IDclient,void* _app,size_t _notreaded);
#endif /* __INTERNALFTPSERVER__*/
